import current from '../core/current';
import logger from '../core/logger';
import allGiftsModel from '../model/live/allGiftsModel';
import giftTopListModel from '../model/live/giftTopListModel';
import guardRankListModel from '../model/live/guardRankListModel';
import liveMyGiftsModel from '../model/live/liveMyGiftsModel';
import livePlayUrlsModel from '../model/live/livePlayUrlsModel';
import liveRoomInfoModel from '../model/live/liveRoomInfoModel';
import liveRoomRankItemModel from '../model/live/liveRoomRankItemModel';
import liveUpModel from '../model/live/liveUpModel';
import medalRankListModel from '../model/live/medalRankListModel';
import roundModel, { roundPlayModel } from '../model/live/roundModel';
import returnModel from '../model/common/returnModel';
import apiInfo from './core/apiInfo';
import apiProvider from './core/apiProvider';
import { clientBase } from './core/clientBase';
import dataInfo from './core/dataInfo';

export class liveRoomClient extends clientBase {
  private readonly gifts: Array<allGiftsModel> = [];

  constructor() {
    super();
    this.getAllGifts();
  }

  getRoomInfo(roomid: string): Promise<returnModel<liveRoomInfoModel>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.live.bilibili.com/xlive/app-room/v1/index/getInfoByRoom", `&room_id=${roomid}`, null, true);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            let data: liveRoomInfoModel = res.data;
            resolve(self.buildSuccessResult<liveRoomInfoModel>(data));
          } else
            resolve(self.buildFailedResult<liveRoomInfoModel>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<liveRoomInfoModel>(e));
      }
    });
  }

  getUpInfo(userid: number): Promise<returnModel<liveUpModel>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.live.bilibili.com/live_user/v1/card/card_up", `&uid=${userid}`, null, true);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            let data: liveUpModel = res.data;
            resolve(self.buildSuccessResult<liveUpModel>(data));
          } else
            resolve(self.buildFailedResult<liveUpModel>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<liveUpModel>(e));
      }
    });
  }

  getRoomPlayurl(roomid: string, quality: number): Promise<returnModel<livePlayUrlsModel>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        this.client.getResult(`https://api.live.bilibili.com/xlive/web-room/v1/playUrl/playUrl?cid=${roomid}&qn=${quality}&platform=web`).then((res) => {
          if (res.code == 0) {
            let data: livePlayUrlsModel = res.data;
            resolve(self.buildSuccessResult<livePlayUrlsModel>(data));
          } else
            resolve(self.buildFailedResult<livePlayUrlsModel>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<livePlayUrlsModel>(e));
      }
    });
  }

  getRoundPlayurl(roomid: string): Promise<returnModel<roundModel>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.live.bilibili.com/live/getRoundPlayVideo", `room_id=${roomid}&type=flv`, null, false);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            let data: roundModel = res.data;
            self.client.getResult(data.play_url).then((res) => {
              let m: roundPlayModel = res;
              data.data = m;
              resolve(self.buildSuccessResult<roundModel>(data));
            }).catch(() => resolve(self.buildSuccessResult<roundModel>(data)));
          } else
            resolve(self.buildFailedResult<roundModel>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<roundModel>(e));
      }
    });
  }

  sendDanmu(text: string, roomId: string): Promise<returnModel<any>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.live.bilibili.com/api/sendmsg", "&actionKey=appkey", null, true);
        let sendText = `cid=${roomId}&mid=${current.instance.mid}&msg=${text}&rnd=${apiProvider.timeSpanSeconds}&mode=1&pool=0&type=json&color=16777215&fontsize=25&playTime=0.0`;
        this.client.postResult(info, sendText).then((res) => {
          if (res.code == 0)
            resolve(self.buildSuccessResult<any>());
          else
            resolve(self.buildFailedResult<any>(res.msg));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<any>(e));
      }
    });
  }

  private getAllGifts(): Promise<returnModel<Array<allGiftsModel>>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.live.bilibili.com/gift/v3/live/gift_config", "actionKey=appkey", null, false);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            let m: Array<allGiftsModel> = res.data;
            self.gifts.length = 0;
            m.forEach((item) => self.gifts.push(item));
            resolve(self.buildSuccessResult<Array<allGiftsModel>>(m));
          } else
            resolve(self.buildFailedResult<Array<allGiftsModel>>(res.msg));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<Array<allGiftsModel>>(e));
      }
    });
  }

  getMyGifts(): Promise<returnModel<Array<liveMyGiftsModel>>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        if (!current.instance.isLogin)
          resolve(self.buildFailedResult<Array<liveMyGiftsModel>>('请先登录'));
        else {
          if (this.gifts.length > 0) {
            let info = new apiInfo("https://api.live.bilibili.com/gift/v2/gift/bag_list", "&actionKey=appkey", null, true);
            this.client.getResult(info).then((res) => {
              if (res.code == 0) {
                let m: Array<liveMyGiftsModel> = res.data.list;
                m.forEach((item: liveMyGiftsModel) => {
                  item.img = this.gifts.find((i) => i.id == item.gift_id)?.img_basic
                });
                resolve(self.buildSuccessResult<Array<liveMyGiftsModel>>(m));
              } else
                resolve(self.buildFailedResult<Array<liveMyGiftsModel>>(res.msg));
            });
          } else {
            this.getAllGifts().then((res) => {
              if (res.success) {
                let info = new apiInfo("https://api.live.bilibili.com/gift/v2/gift/bag_list", "&actionKey=appkey", null, true);
                this.client.getResult(info).then((res) => {
                  if (res.code == 0) {
                    let m: Array<liveMyGiftsModel> = res.data.list;
                    m.forEach((item: liveMyGiftsModel) => {
                      item.img = this.gifts.find((i) => i.id == item.gift_id)?.img_basic
                    });
                    resolve(self.buildSuccessResult<Array<liveMyGiftsModel>>(m));
                  } else
                    resolve(self.buildFailedResult<Array<liveMyGiftsModel>>(res.msg));
                });
              } else
                resolve(self.buildFailedResult<Array<liveMyGiftsModel>>(res.msg));
            });
          }
        }
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<any>(e));
      }
    });
  }

  sendGift(uid: number, ruid: string, gift_id: number, gift_num: number, roomid: string, coin_type: string, price: number): Promise<returnModel<any>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new dataInfo(`actionKey=appkey&biz_code=live&biz_id=${roomid}&coin_type=${coin_type}&gift_id=${gift_id}&gift_num=${gift_num}&price=${price}&rnd=${apiProvider.timeSpanSeconds}&ruid=${ruid}&uid=${uid}`, apiProvider.Build5);
        this.client.postResult("https://api.live.bilibili.com/gift/v2/live/send", info).then((res) => {
          if (res.code == 0)
            resolve(self.buildSuccessResult<any>());
          else
            resolve(self.buildFailedResult<any>(res.msg));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<any>(e));
      }
    });
  }

  sendMyGift(uid: number, ruid: string, gift_id: number, gift_num: number, bag_id: number, roomid: string): Promise<returnModel<any>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.live.bilibili.com/gift/v2/live/bag_send", "&actionKey=appkey", null, true);
        let content = `uid=${uid}&ruid=${ruid}&gift_id=${gift_id}&gift_num=${gift_num}&bag_id=${bag_id}&biz_id=${roomid}&rnd=${apiProvider.timeSpanSeconds}&biz_code=live`;
        this.client.postResult(info, content).then((res) => {
          if (res.code == 0)
            resolve(self.buildSuccessResult<any>());
          else
            resolve(self.buildFailedResult<any>(res.msg));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<any>(e));
      }
    });
  }

  getGuardRank(uid: number, roomId: string): Promise<returnModel<Array<guardRankListModel>>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.live.bilibili.com/xlive/app-room/v2/guardTab/topList", `&roomid=${roomId}&page=1&page_size=30&ruid=${uid}`, null, true);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            var m: Array<guardRankListModel> = res.data.top3;
            var arr: Array<guardRankListModel> = res.data.list;
            resolve(self.buildSuccessResult<Array<guardRankListModel>>(m.concat(arr)));
          } else
            resolve(self.buildFailedResult<Array<guardRankListModel>>(res.msg));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<Array<guardRankListModel>>(e));
      }
    });
  }

  roomRankList(ruid: number, roomid: string, rank_type: string, next_offset: number = 0): Promise<returnModel<Array<liveRoomRankItemModel>>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.live.bilibili.com/rankdb/v1/RoomRank/tabRanks",
          `&next_offset=${next_offset}&room_id=${roomid}&ruid=${ruid}&rank_type=${rank_type}`, null, false);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            var arr: Array<liveRoomRankItemModel> = res.data.list;
            resolve(self.buildSuccessResult<Array<liveRoomRankItemModel>>(arr));
          } else
            resolve(self.buildFailedResult<Array<liveRoomRankItemModel>>(res.msg));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<Array<liveRoomRankItemModel>>(e));
      }
    });
  }

  getGiftTop(roomid: number): Promise<returnModel<Array<giftTopListModel>>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.live.bilibili.com/AppRoom/getGiftTop", `actionKey=appkey&room_id=${roomid}`, null, false);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            var arr: Array<giftTopListModel> = res.data.list;
            resolve(self.buildSuccessResult<Array<giftTopListModel>>(arr));
          } else
            resolve(self.buildFailedResult<Array<giftTopListModel>>(res.msg));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<Array<giftTopListModel>>(e));
      }
    });
  }

  getMedalRankList(roomid: string): Promise<returnModel<Array<medalRankListModel>>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.live.bilibili.com/AppRoom/medalRankList", `actionKey=appkey&room_id=${roomid}`, null, false);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            var arr: Array<medalRankListModel> = res.data.list;
            resolve(self.buildSuccessResult<Array<medalRankListModel>>(arr));
          } else
            resolve(self.buildFailedResult<Array<medalRankListModel>>(res.msg));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<Array<medalRankListModel>>(e));
      }
    });
  }

  getRoomGifts(roomid: number, area_v2_id: number, area_v2_parent_id: number): Promise<returnModel<Array<allGiftsModel>>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        if (!current.instance.isLogin)
          resolve(self.buildFailedResult<Array<allGiftsModel>>('请先登录'));
        else {
          if (this.gifts.length > 0) {
            let info = new apiInfo("https://api.live.bilibili.com/gift/v3/live/room_gift_list", `actionkey=appkey&area_v2_id=${area_v2_id}&area_v2_parent_id=${area_v2_parent_id}&roomid=${roomid}`, null, true);
            this.client.getResult(info).then((res) => {
              if (res.code == 0) {
                var arr: Array<allGiftsModel> = [];
                for (var item of res.data.list) {
                  var gift = this.gifts.find((i) => i.id == item.id);
                  arr.push(gift);
                }
                resolve(self.buildSuccessResult<Array<allGiftsModel>>(arr));
              } else
                resolve(self.buildFailedResult<Array<allGiftsModel>>(res.msg));
            });
          } else {
            resolve(self.buildFailedResult<Array<allGiftsModel>>('无法读取礼物'));
          }
        }
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<any>(e));
      }
    });
  }

  roomEntryAction(roomId: string): Promise<returnModel<any>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.live.bilibili.com/room/v1/Room/room_entry_action", `&actionKey=appkey&room_id=${roomId}`, null, true);
        this.client.getResult(info).then((res) => {
          if (res.code == 0)
            resolve(self.buildSuccessResult<any>(res));
          else
            resolve(self.buildFailedResult<any>(res.msg));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<any>(e));
      }
    });
  }
}
export default new liveRoomClient();